package org.example.greenhouse.service.impl;

import org.example.greenhouse.common.dao.BaseSoliDao;
import org.example.greenhouse.common.entity.BaseSoli;
import org.example.greenhouse.dao.*;
import org.example.greenhouse.entity.*;
import org.example.greenhouse.result.Result;
import org.example.greenhouse.result.SoliResult;
import org.example.greenhouse.service.DeviceService;
import org.example.greenhouse.service.SensorService;
import org.example.greenhouse.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class SensorServiceImpl implements SensorService {
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private Soli1Dao soli1Dao;
    @Autowired
    private Soli2Dao soli2Dao;
    @Autowired
    private Soli3Dao soli3Dao;
    @Autowired
    private Soli4Dao soli4Dao;
    @Autowired
    private Soli5Dao soli5Dao;
    @Autowired
    private DeviceDao deviceDao;

    @Value("${sensor.url}")
    private String sensorUrl;

    @Value("${greenHouseId}")
    private String greenHouseId;

    @Override
    public Result fetchAndSaveSensorData() {
        try {
            // 获取所有土壤检测设备的 serialNumber
            List<Device> soilDevices = deviceService.getSoilDetectionDevices();
            List<String> serialNumbersList = soilDevices.stream()
                    .map(Device::getSerialNumber)
                    .collect(Collectors.toList());
            List<Integer> deviceIds = soilDevices.stream()
                    .map(Device::getDeviceId)
                    .collect(Collectors.toList());

            // 发送请求获取传感器数据
            String url = sensorUrl.replace("{boxNo}", greenHouseId);
            List<BaseSoli> sensorData = fetchSensorData(url, serialNumbersList);

            // 将数据按顺序存储到 soli1, soli2 等表中
            saveSensorData(sensorData, deviceIds);

            return Result.success("传感器数据更新成功！");
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常堆栈
            return Result.error("传感器数据更新失败：" + e.getMessage());
        }
    }

    @Override
    public <T extends BaseSoli> Result getAllSensorData(Class<T> entityClass) {
        try {
            BaseSoliDao<T, Integer> dao = getDaoForEntity(entityClass);
            List<T> soliList = dao.findAll();
            if (soliList.isEmpty()) {
                return Result.error("未找到 soli 数据");
            }
            // 获取第一个 soli 数据的 deviceId
            int deviceId = soliList.get(0).getDeviceId();
            // 查询对应的 Device 数据
            Optional<Device> deviceOptional = deviceDao.findById(deviceId);
            // 封装返回结果
            SoliResult<T> result = new SoliResult<>(deviceOptional.get(), soliList);
            return Result.success(result);
        } catch (Exception e) {
            return Result.error("获取传感器数据失败：" + e.getMessage());
        }
    }

    /**
     * 根据实体类获取对应的 Dao
     */
    @SuppressWarnings("unchecked")
    private <T extends BaseSoli> BaseSoliDao<T, Integer> getDaoForEntity(Class<T> entityClass) {
        if (entityClass.equals(soli1.class)) {
            return (BaseSoliDao<T, Integer>) soli1Dao;
        } else if (entityClass.equals(soli2.class)) {
            return (BaseSoliDao<T, Integer>) soli2Dao;
        } else if (entityClass.equals(soli3.class)) {
            return (BaseSoliDao<T, Integer>) soli3Dao;
        } else if (entityClass.equals(soli4.class)) {
            return (BaseSoliDao<T, Integer>) soli4Dao;
        } else if (entityClass.equals(soli5.class)) {
            return (BaseSoliDao<T, Integer>) soli5Dao;
        } else {
            throw new IllegalArgumentException("不支持的实体类: " + entityClass.getSimpleName());
        }
    }



    /**
     * 发送请求获取传感器数据
     */
    private List<BaseSoli> fetchSensorData(String url, List<String> sensorIds) {
        // 获取最新的 Token
        Token token = tokenService.getLatestToken();
        if (token == null) {
            throw new RuntimeException("未获取到有效的 Token");
        }

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + token.getAccess_token());
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 设置请求体
        Map<String, List<String>> requestBody = new HashMap<>();
        requestBody.put("ids", sensorIds);

        // 发送 POST 请求
        HttpEntity<Map<String, List<String>>> request = new HttpEntity<>(requestBody, headers);
        ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                request,
                new ParameterizedTypeReference<List<Map<String, Object>>>() {}
        );

        if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
            // 将 API 返回的数据映射到 BaseSoli 对象
            return IntStream.range(0, response.getBody().size())
                    .mapToObj(i -> mapToBaseSoli(response.getBody().get(i), i))
                    .collect(Collectors.toList());
        } else {
            throw new RuntimeException("获取传感器数据失败");
        }
    }

    /**
     * 将 API 返回的数据映射到 BaseSoli 对象
     */
    private BaseSoli mapToBaseSoli(Map<String, Object> sensorData, int index) {
        BaseSoli baseSoli;
        switch (index) {
            case 0:
                baseSoli = new soli1();
                break;
            case 1:
                baseSoli = new soli2();
                break;
            case 2:
                baseSoli = new soli3();
                break;
            case 3:
                baseSoli = new soli4();
                break;
            case 4:
                baseSoli = new soli5();
                break;
            default:
                throw new IllegalArgumentException("无效的索引: " + index);
        }

        // 设置字段
        baseSoli.setName((String) sensorData.get("name"));
        baseSoli.setValue(sensorData.get("value") instanceof Integer ?
                ((Integer) sensorData.get("value")).doubleValue() :
                (Double) sensorData.get("value"));
        baseSoli.setTimestamp((String) sensorData.get("timestamp"));
        baseSoli.setStatus((Integer) sensorData.get("status"));

        return baseSoli;
    }

    /**
     * 存储传感器数据
     */
    private void saveSensorData(List<BaseSoli> baseSoliList, List<Integer> deviceIds) {
        // 1. 为每个 BaseSoli 设置 deviceId
        for (int i = 0; i < baseSoliList.size(); i++) {
            BaseSoli baseSoli = baseSoliList.get(i);
            baseSoli.setDeviceId(deviceIds.get(i)); // 设置 deviceId
        }

        // 2. 将 BaseSoli 存储到对应的表中
        for (int i = 0; i < baseSoliList.size(); i++) {
            BaseSoli baseSoli = baseSoliList.get(i);
            switch (i) {
                case 0:
                    soli1Dao.save((soli1) baseSoli); // 存储到 soli1 表
                    break;
                case 1:
                    soli2Dao.save((soli2) baseSoli); // 存储到 soli2 表
                    break;
                case 2:
                    soli3Dao.save((soli3) baseSoli); // 存储到 soli3 表
                    break;
                case 3:
                    soli4Dao.save((soli4) baseSoli); // 存储到 soli4 表
                    break;
                case 4:
                    soli5Dao.save((soli5) baseSoli); // 存储到 soli5 表
                    break;
                default:
                    throw new IllegalArgumentException("超出表的数量限制");
            }
        }
    }
}